﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.IO;
using System.Text;
using System.Windows.Forms;

namespace FORUs
{
    public partial class SongsTreeview : UserControl
    {
        public enum DisplayMode
        {
            None, Directory, Edition, Language, Genre, Artist, Song
        }

        #region Icons 
        static Dictionary<DisplayMode, string> _dicKeys = null;
        static ImageList _imgIcons = null;


        private static string GetIcon(DisplayMode mode)
        {
            if (_dicKeys == null)
                LoadIcons();

            return _dicKeys[mode];
        }

        private static void LoadIcons()
        {
            _dicKeys = new Dictionary<DisplayMode, string>();
            _imgIcons = new ImageList();

            _dicKeys.Add(DisplayMode.Song, "songtitle");
            _imgIcons.Images.Add("songtitle", Properties.Resources.icoTreeviewSongtitle);
            _dicKeys.Add(DisplayMode.Language, "language");
            _imgIcons.Images.Add("language", Properties.Resources.icoTreeviewLanguage);
            _dicKeys.Add(DisplayMode.Edition, "edition");
            _imgIcons.Images.Add("edition", Properties.Resources.icoTreeviewEdition);
            _dicKeys.Add(DisplayMode.Artist, "artist");
            _imgIcons.Images.Add("artist", Properties.Resources.icoTreeviewArtist);
            _dicKeys.Add(DisplayMode.Genre, "genre");
            _imgIcons.Images.Add("genre", Properties.Resources.icoTreeviewGenre);
            _dicKeys.Add(DisplayMode.None, "none");
            _imgIcons.Images.Add("none", Properties.Resources.icoTreeviewNone);
            
            _imgIcons.Images.Add("song", Properties.Resources.icoTreeviewSong);
        }

        #endregion

        #region Variables
        List<UltrastarSong> _lsSongs;
        string _sSongDirectory;
        DisplayMode _dMode = DisplayMode.None;
        #endregion
        
        #region EventHandlers
        public event TreeViewEventHandler AfterSongSelect
        {
            add {_trvSongs.AfterSelect += value;}
            remove {_trvSongs.AfterSelect -= value;}
        }

        public event TreeViewCancelEventHandler BeforeSongSelect
        {
            add {_trvSongs.BeforeSelect += value;}
            remove {_trvSongs.BeforeSelect -= value;}
        }
        #endregion

        #region Properties
        [Category("Behavior")]
        public string SongDirectory
        {
            get { return _sSongDirectory; }
            set { _sSongDirectory = value; }
        }
        [Category("Appearance")]
        public DisplayMode Mode
        {
            get { return _dMode; }
            set { _dMode = value; }
        }

        public UltrastarSong SelectedSong
        {
            get
            {
                if (_trvSongs.SelectedNode != null)
                {
                    int i = -1;
                    try
                    {
                        i = Convert.ToInt32(_trvSongs.SelectedNode.Name);
                    }
                    catch (FormatException)
                    {
                        i = -1;
                    }
                    if (i >= 0)
                        return _lsSongs[i];
                    else
                        return UltrastarSong.Empty;
                }
                else
                    return UltrastarSong.Empty;
            }
        }

        public int CountSongs
        {
            get { return _lsSongs.Count; }
        }
        #endregion

        #region Constructors
        public SongsTreeview()
        {
            InitializeComponent();

            _lsSongs = new List<UltrastarSong>();
            LoadIcons();
            _trvSongs.ImageList = _imgIcons;
        }

        public SongsTreeview(string songDirectory) : this()
        {
            _sSongDirectory = songDirectory;
        }

        public SongsTreeview(string songDirectory, DisplayMode mode) : this(songDirectory)
        {
            _dMode = mode;
        }
        #endregion

        #region Loading Songs
        private bool LoadSongs()
        {
            // Clearing the list
            _lsSongs.Clear();

            // Checking the existence of the directory
            DirectoryInfo directory = new DirectoryInfo(_sSongDirectory);
            if (!directory.Exists)
                return false;

            // Scanning the Directory
            FileInfo[] files = directory.GetFiles("*.txt", SearchOption.AllDirectories);
            foreach (FileInfo f in files)
            {
                UltrastarSong uSong = UltrastarSong.FromFile(f.FullName);
                if (!uSong.IsEmpty)
                    _lsSongs.Add(uSong);
            }

            // Displayong the numbers of songs
            _lblCount.Text = string.Concat("(", CountSongs.ToString(), ")");

            return true;
        }

        public bool DisplaySongs()
        {
            // Loading the songs
            if (!LoadSongs())
                return false;

            // Sorting the Songs
            SortSongs();

            // Clearing the treeview
            _trvSongs.Nodes.Clear();

            int i = 0;
            while (i < _lsSongs.Count)
            {
                // Getting the root node of the current song
                TreeNode rootNode = GetRootNode(_lsSongs[i]);
                // Adding the songs related to this root node
                while ((i < _lsSongs.Count) && !HasToChangeRoot(_lsSongs[i], rootNode))
                {
                    rootNode.Nodes.Add(i.ToString(), _lsSongs[i].CompleteTitle, "song", "song");
                    i++;
                }
            }

            // Collapsing all the nodes
            _trvSongs.CollapseAll();

            return true;
        }

        private void SortSongs()
        {
            switch (_dMode)
            {
                case DisplayMode.None:
                    _lsSongs.Sort(UltrastarSong.CompareByCompleteTitle);
                    break;
                case DisplayMode.Artist:
                    _lsSongs.Sort(UltrastarSong.CompareByArtist);
                    break;
                case DisplayMode.Song:
                    _lsSongs.Sort(UltrastarSong.CompareByTitle);
                    break;
                case DisplayMode.Directory:
                    _lsSongs.Sort(UltrastarSong.CompareByFilename);
                    break;
                case DisplayMode.Edition:
                    _lsSongs.Sort(UltrastarSong.CompareByEdition);
                    break;
                case DisplayMode.Genre:
                    _lsSongs.Sort(UltrastarSong.CompareByGenre);
                    break;
                case DisplayMode.Language:
                    _lsSongs.Sort(UltrastarSong.CompareByLanguage);
                    break;
            }
        }

        private TreeNode GetRootNode(UltrastarSong uSong)
        {
            TreeNode rootNode = null;
            
            switch (_dMode)
            {
                case DisplayMode.None:
                    rootNode = _trvSongs.Nodes.Add("all", "Toutes les chansons", GetIcon(_dMode), GetIcon(_dMode));
                    break;
                case DisplayMode.Artist:
                    rootNode = _trvSongs.Nodes.Add(uSong.Artist, uSong.Artist, GetIcon(_dMode), GetIcon(_dMode));
                    break;
                case DisplayMode.Song:
                    rootNode = _trvSongs.Nodes.Add(uSong.Title, uSong.Title, GetIcon(_dMode), GetIcon(_dMode));
                    break;
                case DisplayMode.Directory:
                    rootNode = GetDirectoryNode(uSong.Filename);
                    break;
                case DisplayMode.Edition:
                    rootNode = _trvSongs.Nodes.Add(uSong.Edition, uSong.Edition, GetIcon(_dMode), GetIcon(_dMode));
                    break;
                case DisplayMode.Genre:
                    rootNode = _trvSongs.Nodes.Add(uSong.Genre, uSong.Genre, GetIcon(_dMode), GetIcon(_dMode));
                    break;
                case DisplayMode.Language:
                    rootNode = _trvSongs.Nodes.Add(uSong.Language, uSong.Language, GetIcon(_dMode), GetIcon(_dMode));
                    break;
            }

            return rootNode;
        }

        private TreeNode GetDirectoryNode(string filename)
        {
            // TODO
            return _trvSongs.Nodes.Add("all", "Toutes les chansons"); ;
        }

        private bool HasToChangeRoot(UltrastarSong uSong, TreeNode rootNode)
        {
            bool bContinue = true;
            switch (_dMode)
            {
                case DisplayMode.None:
                    bContinue = true;
                    break;
                case DisplayMode.Artist:
                    bContinue = uSong.Artist.Equals(rootNode.Name);
                    break;
                case DisplayMode.Song:
                    bContinue = uSong.Title.Equals(rootNode.Name);
                    break;
                case DisplayMode.Directory:
                    bContinue = true; // TODO
                    break;
                case DisplayMode.Edition:
                    bContinue = uSong.Edition.Equals(rootNode.Name);
                    break;
                case DisplayMode.Genre:
                    bContinue = uSong.Genre.Equals(rootNode.Name);
                    break;
                case DisplayMode.Language:
                    bContinue = uSong.Language.Equals(rootNode.Name);
                    break;
            }
            return !bContinue;
        }
        #endregion

        #region Buttons Events
        private void _btnLoadNone_Click(object sender, EventArgs e)
        {
            _dMode = DisplayMode.None;
            DisplaySongs();
        }

        private void _btnLoadDirectory_Click(object sender, EventArgs e)
        {
            _dMode = DisplayMode.Directory;
            DisplaySongs();
        }

        private void _btnLoadArtist_Click(object sender, EventArgs e)
        {
            _dMode = DisplayMode.Artist;
            DisplaySongs();
        }

        private void _btnLoadSongs_Click(object sender, EventArgs e)
        {
            _dMode = DisplayMode.Song;
            DisplaySongs();
        }

        private void _btnLoadEdition_Click(object sender, EventArgs e)
        {
            _dMode = DisplayMode.Edition;
            DisplaySongs();
        }

        private void _btnLoadGenres_Click(object sender, EventArgs e)
        {
            _dMode = DisplayMode.Genre;
            DisplaySongs();
        }

        private void _btnLoadLanguage_Click(object sender, EventArgs e)
        {
            _dMode = DisplayMode.Language;
            DisplaySongs();
        }
        #endregion
    }
}
